package io.github.jyrmc.deploy.task

import io.github.jyrmc.deploy.entity.KubernetesNamespaceEntity
import io.github.jyrmc.deploy.utils.CommandLineUtils
import io.github.jyrmc.deploy.utils.DataUtils
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction

/**
 * k8s deploy task
 *
 * @author jy
 * @since 2023/5/16 11:24
 **/
open class DeployToKubernetesTask : DefaultTask() {
    @Input
    @Optional
    lateinit var host: String

    @Input
    var port: Int = 22

    @Input
    var username: String = "root"

    @Input
    @Optional
    lateinit var password: String

    @Input
    @Optional
    var commandLine: String = ""

    @Input
    @Optional
    lateinit var imagePrefix: String

    @Input
    @Optional
    lateinit var imageName: String

    @Input
    @Optional
    lateinit var imageVersion: String

    @Input
    @Optional
    lateinit var deploymentName: String

    @Input
    var namespace: String = "default"


    @TaskAction
    fun deployKubernetesAction() {
        if (host.isBlank()) {
            println("host can't be null or empty")
            return
        }
        if (password.isBlank()) {
            println("password can't be null or empty")
            return
        }
        if (imageName.isBlank()) {
            println("imageName can't be null or empty")
            return
        }
        if (imageVersion.isBlank()) {
            println("imageVersion can't be null or empty")
            return
        }

        println("🐙🐙🐙 Start to Deploy to Kubernetes 🐙🐙🐙")
        // 获取k8s命名空间
        val namespaceCommandLine = "kubectl get namespace"
        val namespaceResponse = CommandLineUtils.exec(host, port, username, password, namespaceCommandLine)
        val namespaceData = DataUtils.getNamespaces(namespaceResponse)
        val predicate: (KubernetesNamespaceEntity) -> Boolean = { it.name == namespace }
        val match = namespaceData.any(predicate)
        if (!match) {
            println("🚨🚨🚨Namespace $namespace ==> Not Exists, Please check it on your k8s🚨🚨🚨")
            return
        }

        // check the pod is exists or not
        val podStatusCommandLine = "kubectl get pods -n $namespace | grep $deploymentName"
        val result = CommandLineUtils.exec(host, port, username, password, podStatusCommandLine)
        if (result.isBlank()) {
            println("🚨🚨🚨Deployment $deploymentName ==> Not Exists, Please check it on your k8s🚨🚨🚨")
            return
        }

        // validate has any pod on runing before deploy new image, if the namespace has no pod on runing,
        // try to set replicas to 1 and deploy the new image
        val podsScaleCommandLine = "kubectl get deployment $deploymentName -n $namespace"
        val podsScaleResponse = CommandLineUtils.exec(host, port, username, password, podsScaleCommandLine)
        val podInfo = DataUtils.getPodInfo(podsScaleResponse)[0]
        if (podInfo.available == 0) {
            println("⚡⚡⚡⚡⚡⚡⚡ pod -> $deploymentName on namespace -> $namespace is not runing, now will auto set replicas to 1, wait 10s")
            val scaleCommandLine = "kubectl scale deployment/$deploymentName --replicas=1 -n $namespace"
            val scaleResponse = CommandLineUtils.exec(host, port, username, password, scaleCommandLine)
            println("🚩🚩🚩${scaleResponse}")
            // thread sleep 10s
            Thread.sleep(10000)
        }

        // 构建部署k8s命令
        val deployK8sCommandLine =
            "kubectl -n $namespace set image deployment/${deploymentName} ${imageName}=${imagePrefix}/${imageName}:${imageVersion}"
        val deployResponse = CommandLineUtils.exec(host, port, username, password, deployK8sCommandLine)
        println(deployResponse)

        val statusCommandLine = "kubectl rollout status deployment/${deploymentName}"
        println("Deploy Result As Follow: 🚩🚩🚩⬅️")
        CommandLineUtils.exec(host, port, username, password, statusCommandLine)
        println("🐙🐙🐙 Finish to Deploy to Kubernetes 🐙🐙🐙")
    }
}